/**
 * Created by AMD on 24.11.14.
 */
package model.objects {
import flash.geom.Point;

import model.Constants;

import model.prototypes.ShopObjectProto;

import org.osflash.signals.Signal;

import signals.UpdateDataSignal;

import signals.UpdateDataSignal;


public class ShopObjectData {
    protected var _position:Point = new Point();
    protected var _angle:int = 45;
    protected var _params:Array = null;
    private var _rotatedOCCMatrix:Array;

    private static var _shopObjectIdCounter:uint = 0;

    private var _proto:ShopObjectProto;
    private var _id:String;

    protected var _updateSignal:UpdateDataSignal = new UpdateDataSignal();

    protected var _highlightMode:int = 0;

    public function ShopObjectData(proto:ShopObjectProto, params:Array = null) {
        this._proto = proto;
        this._params = params;

        this.angle = this._angle;

        _shopObjectIdCounter ++;
        this._id = Constants.SHOP_OBJECT_ID_PREFIX + ShopObjectData._shopObjectIdCounter;

        this._updateSignal.sendSignal(Constants.OBJECT_CREATED_SIGNAL, this);
    }



    public function get proto():ShopObjectProto {
        return _proto;
    }

    /// stringCoords example = "x1y2"
    public static function convertPosition(stringCoords:String):Point{
        var bufArray:Array = stringCoords.substring(1,stringCoords.length).split("y");
        return new Point(int(bufArray[0]),int(bufArray[1]));
    }

    /// @vector  :  point2 - point1
    public static function getAngleByVector(vector:Point):int {
        //vector.normalize(1)
        var _result:int = 45;
        if(Math.abs(vector.x) > Math.abs(vector.y)){
            if (vector.x < 0){
                _result = 315;
            } else if(vector.x > 0){
                _result = 135
            }
        } else {
            if (vector.y < 0){
                _result = 45;
            } else if(vector.y > 0){
                _result = 225
            }
        }
        return _result;
    }

    /// default_occ_matrix example = [[1,1,1],[1,1,1],[1,1,1]]   (any square matrix)
    public static function rotateOCCMatrix(default_occ_matrix:Array, angle:int = 45):Array{
        var _result:Array = default_occ_matrix;
        switch (angle){
            case 135:
                    _result = ShopObjectData._rotate90Right(default_occ_matrix);
                break;
            case 225:
                    _result = ShopObjectData._rotate180(default_occ_matrix);
                break;
            case 315:
                    _result = ShopObjectData._rotate90Left(default_occ_matrix);
                break;
        }

        return _result;
    }

    private static function _rotate90Left(default_occ_matrix:Array):Array {
        var x:int = 0;
        var y:int = 0;
        var _currentElement:int;
        var _result:Array = [];
        var martixSize:int = default_occ_matrix.length
        for(y = 0; y < (default_occ_matrix as Array).length ; y++){
            for(x = 0; x < (default_occ_matrix[y] as Array).length; x++){
                _currentElement = default_occ_matrix[y][x];
                if(y == 0){
                    _result.unshift([]);
                    (_result[0] as Array).push(_currentElement);
                } else {
                    (_result[martixSize - 1 - x] as Array).push(_currentElement);
                }

            }
        }

        return _result;
    }
    private static function _rotate180(default_occ_matrix:Array):Array {
        var x:int = 0;
        var y:int = 0;
        var _currentElement:int;
        var _result:Array = [];
        for(y = 0; y < (default_occ_matrix as Array).length ; y++){
            for(x = 0; x < (default_occ_matrix[y] as Array).length; x++){
                if(x == 0){
                    _result.unshift([]);
                }
                _currentElement = default_occ_matrix[y][x];
                (_result[0] as Array).unshift(_currentElement);
            }
        }

        return _result;
    }

    private static function _rotate90Right(default_occ_matrix:Array):Array{
        var x:int = 0;
        var y:int = 0;
        var _currentElement:int;
        var _result:Array = [];
        for(y = 0; y < (default_occ_matrix as Array).length ; y++){
            for(x = 0; x < (default_occ_matrix[y] as Array).length; x++){
                if(y == 0){
                    _result.push([]);
                }
                _currentElement = default_occ_matrix[y][x];
                (_result[x] as Array).unshift(_currentElement);
            }
        }

        return _result;
    }


    public function set params(value:Array):void {
       this._params = value;
        this._updateSignal.sendSignal(Constants.OBJECT_PARAMS_UPDATE_SIGNAL, this._params);
    }

    public function get params():Array {
        return this._params;
    }

    public function get angle():int {
        return _angle;
    }

    public function set angle(value:int):void {
        while(value < 0){
            value += 360;
        }
        while(value > 360){
            value -= 360;
        }
        this._angle = value;
        if(this.proto.sideIsDisabled(value)){
            this._angle = this._getSimilarAngle(value);
        }
        this._rotatedOCCMatrix = rotateOCCMatrix(this.proto.occ_matrix,this._angle);

        this._updateSignal.sendSignal(Constants.OBJECT_ANGLE_UPDATE_SIGNAL, this._angle);
    }

    public function get rotatedOCCMatrix():Array {
        return _rotatedOCCMatrix;
    }

    private function _getSimilarAngle(value:int):int {
        switch (value){
            case 45:
                    return 225;
                break;
            case 135:
                    return 315;
                break;
            case 225:
                    return 45;
                break;
            case 315:
                    return 135;
                break;
        }
        return -1;
    }

    public function destruct():void {
        this._updateSignal.sendSignal(Constants.OBJECT_DESTOY_SIGNAL, this);
    }


    public function get id():String {
        return _id;
    }

    public function get updateSignal():UpdateDataSignal {
        return _updateSignal;
    }


    public function get position():Point {
        return _position;
    }

    public function set position(value:Point):void {
        this._position = value.clone();

        this._updateSignal.sendSignal(Constants.OBJECT_POSITION_UPDATE_SIGNAL, this._position);
    }

    public function get highlightMode():int {
        return _highlightMode;
    }

    public function set highlightMode(value:int):void {
        this._highlightMode = value;
        this._updateSignal.sendSignal(Constants.OBJECT_TOGGLE_HIGHLIGHT_SIGNAL, value);
    }
}
}
